

using System;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Xml;
using SunRiseSoft.Library.Configuration;

namespace SunRiseSoft.Library.DataAccess
{

	public class SqlDatabase : Database
	{
#region "Construction"
        protected SqlDatabase(string connectionName, string connectionString)
            : base(connectionName, connectionString, SqlClientFactory.Instance)
        {
        }
        
        public SqlDatabase()
            : this(ConfigurationManager.Connection.Name, ConfigurationManager.Connection.ConnectionString)
        {
        }

        public SqlDatabase(string connectionName)
            : this(ConfigurationManager.Connections[connectionName].Name, ConfigurationManager.Connections[connectionName].ConnectionString)
        {
        }

        public static SqlDatabase CreateDatabase(string connectionName, string connectionString)
        {
            return new SqlDatabase(connectionName, connectionString);
        }

        public static SqlDatabase CreateDatabase(string connectionString)
		{
            return new SqlDatabase("DefaultName", connectionString);
        }

#endregion
#region "AddInParameter"
		public DbParameter AddInParameter(DbCommand command, string name, SqlDbType dbType, object value)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.Input, value);
		}

		public DbParameter AddInParameter(DbCommand command, string name, SqlDbType dbType, int size, object value)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.Input, value);
		}

		public DbParameter AddInOutParameter(DbCommand command, string name, SqlDbType dbType, object value)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.InputOutput, value);
		}

		public DbParameter AddInOutParameter(DbCommand command, string name, SqlDbType dbType, int size, object value)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.InputOutput, value);
		}

		public DbParameter AddOutParameter(DbCommand command, string name, SqlDbType dbType)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.Output, null);
		}

		public DbParameter AddOutParameter(DbCommand command, string name, SqlDbType dbType, int size)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.Output, null);
		}

		public DbParameter AddReturnParameter(DbCommand command, string name, SqlDbType dbType)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.ReturnValue, null);
		}

		public DbParameter AddReturnParameter(DbCommand command, string name, SqlDbType dbType, int size)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.ReturnValue, null);
		}

		public DbParameter AddParameter(DbCommand command, string name, SqlDbType dbType, int size, ParameterDirection direction, object value)
		{
			return AddParameter(command, name, dbType, size, direction, string.Empty, DataRowVersion.Default, value);
		}


		public DbParameter AddInParameter(DbCommand command, string name, SqlDbType dbType, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.Input, sourceColumn, sourceVersion);
		}

		public DbParameter AddInParameter(DbCommand command, string name, SqlDbType dbType, int size, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.Input, sourceColumn, sourceVersion);
		}

		public DbParameter AddInOutParameter(DbCommand command, string name, SqlDbType dbType, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.InputOutput, sourceColumn, sourceVersion);
		}

		public DbParameter AddInOutParameter(DbCommand command, string name, SqlDbType dbType, int size, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.InputOutput, sourceColumn, sourceVersion);
		}

		public DbParameter AddOutParameter(DbCommand command, string name, SqlDbType dbType, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, 0, ParameterDirection.Output, sourceColumn, sourceVersion);
		}

		public DbParameter AddOutParameter(DbCommand command, string name, SqlDbType dbType, int size, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, size, ParameterDirection.Output, sourceColumn, sourceVersion);
		}

		public DbParameter AddParameter(DbCommand command, string name, SqlDbType dbType, int size, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, size, direction, string.Empty, DataRowVersion.Default, null);
		}


		public DbParameter AddParameter(DbCommand command, string name, SqlDbType dbType, int size, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
		{
			DbParameter parameter = CreateParameter(name, dbType, size, direction, sourceColumn, sourceVersion, value);
			command.Parameters.Add(parameter);
			return parameter;
		}




		public DbParameter AddInParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, object value)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.Input, value);
		}

		public DbParameter AddInOutParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, object value)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.InputOutput, value);
		}

		public DbParameter AddOutParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.Output, null);
		}

		public DbParameter AddReturnParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.ReturnValue, null);
		}

		public DbParameter AddParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, ParameterDirection direction, object value)
		{
			return AddParameter(command, name, dbType, precision, scale, direction, string.Empty, DataRowVersion.Default, value);
		}


		public DbParameter AddInParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.Input, sourceColumn, sourceVersion);
		}

		public DbParameter AddInOutParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.InputOutput, sourceColumn, sourceVersion);
		}

		public DbParameter AddOutParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, precision, scale, ParameterDirection.Output, sourceColumn, sourceVersion);
		}

		public DbParameter AddParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion)
		{
			return AddParameter(command, name, dbType, precision, scale, direction, string.Empty, DataRowVersion.Default, null);
		}


		public DbParameter AddParameter(DbCommand command, string name, SqlDbType dbType, byte precision, byte scale, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
		{
			DbParameter parameter = CreateParameter(name, dbType, precision, scale, direction, sourceColumn, sourceVersion, value);
			command.Parameters.Add(parameter);
			return parameter;
		}
#endregion
#region "PrepareParameter"
		//Public Overrides Function BuildParameterName(ByVal name As String) As String
		//    If (name.Chars(0) <> Me.ParameterToken) Then
		//        Return name.Insert(0, New String(Me.ParameterToken, 1))
		//    End If
		//    Return name
		//End Function

		private static SqlCommand CheckIfSqlCommand(DbCommand command)
		{
			SqlCommand cmd = command as SqlCommand;
			if (cmd == null) {
				throw new ArgumentException("command");
			}
			return cmd;
		}

		//Protected Overloads Sub ConfigureParameter(ByVal param As SqlParameter, ByVal name As String, ByVal dbType As SqlDbType, ByVal size As Integer, ByVal direction As ParameterDirection, ByVal nullable As Boolean, ByVal precision As Byte, ByVal scale As Byte, ByVal sourceColumn As String, ByVal sourceVersion As DataRowVersion, ByVal value As Object)
		//    param.SqlDbType = dbType
		//    param.Size = size
		//    If value Is Nothing Then
		//        param.Value = DBNull.Value
		//    Else
		//        param.Value = value
		//    End If
		//    param.Direction = direction
		//    param.IsNullable = nullable
		//    param.SourceColumn = sourceColumn
		//    param.SourceVersion = sourceVersion
		//End Sub

		protected DbParameter CreateParameter(string name, SqlDbType dbType, byte precision, byte scale, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
		{
			SqlParameter param = (SqlParameter)CreateParameter(name);
			param.SqlDbType = dbType;
			param.Precision = precision;
			param.Scale = scale;
			if (value == null) {
				param.Value = DBNull.Value;
			}
			else {
				param.Value = value;
			}
			param.Direction = direction;
			param.SourceColumn = sourceColumn;
			param.SourceVersion = sourceVersion;
			return param;
		}

		protected DbParameter CreateParameter(string name, SqlDbType dbType, int size, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
		{
			SqlParameter param = (SqlParameter)CreateParameter(name);
			param.SqlDbType = dbType;
			param.Size = size;
			if (value == null) {
				param.Value = DBNull.Value;
			}
			else {
				param.Value = value;
			}
			param.Direction = direction;
			param.SourceColumn = sourceColumn;
			param.SourceVersion = sourceVersion;
			return param;
		}

		//Protected Overrides Sub DeriveParameters(ByVal discoveryCommand As DbCommand)
		//    SqlCommandBuilder.DeriveParameters(DirectCast(discoveryCommand, SqlCommand))
		//End Sub
#endregion
#region "ExecuteXmlReader"
		public XmlReader ExecuteXmlReader(DbCommand command)
		{
			SqlCommand cmd = CheckIfSqlCommand(command);
			ConnectionWrapper wrapper = GetOpenConnection(false);
			PrepareCommand(command, wrapper);
			return DoExecuteXmlReader(cmd);
		}

		private XmlReader DoExecuteXmlReader(SqlCommand command)
		{
			try {
				XmlReader reader = command.ExecuteXmlReader();
				_instrumentation.CommandExecuted(command);
				return reader;
			}
			catch (Exception exception) {
				_instrumentation.CommandFailed(command, exception);
				throw;
			}
		}

		//Public Function ExecuteXmlReader(ByVal command As DbCommand, ByVal transaction As DbTransaction) As XmlReader
		//    Dim command2 As SqlCommand = SqlDatabase.CheckIfSqlCommand(command)
		//    Database.PrepareCommand(command2, transaction)
		//    Return Me.DoExecuteXmlReader(command2)
		//End Function
#endregion

		protected override void DeriveParameters(System.Data.Common.DbCommand discoveryCommand)
		{
			SqlCommandBuilder.DeriveParameters((SqlCommand)discoveryCommand);
		}

		//Protected Overrides Function SameNumberOfParametersAndValues(ByVal command As DbCommand, ByVal values As Object()) As Boolean
		//    Dim num As Integer = 1
		//    Dim num2 As Integer = (command.Parameters.Count - num)
		//    Dim length As Integer = values.Length
		//    Return (num2 = length)
		//End Function

		protected override int UserParametersStartIndex {
			get { return 1; }
		}


		// Properties
		//Protected ReadOnly Property ParameterToken() As Char
		//    Get
		//        Return "@"c
		//    End Get
		//End Property

		//Private Sub OnSqlRowUpdated(ByVal sender As Object, ByVal rowThatCouldNotBeWritten As SqlRowUpdatedEventArgs)
		//    If ((rowThatCouldNotBeWritten.RecordsAffected = 0) AndAlso (Not rowThatCouldNotBeWritten.Errors Is Nothing)) Then
		//        rowThatCouldNotBeWritten.Row.RowError = "Failed to update row"
		//        rowThatCouldNotBeWritten.Status = UpdateStatus.SkipCurrentRow
		//    End If
		//End Sub

		//Protected Overrides Sub SetUpRowUpdatedEvent(ByVal adapter As DbDataAdapter)
		//    AddHandler DirectCast(adapter, SqlDataAdapter).RowUpdated, New SqlRowUpdatedEventHandler(AddressOf Me.OnSqlRowUpdated)
		//End Sub

	}

}
